package com.hh.flow.controller;

import com.hh.common.constant.HttpStatus;
import com.hh.common.core.domain.R;
import com.hh.common.core.page.PageDomain;
import com.hh.common.core.page.TableDataInfo;
import com.hh.common.core.page.TableSupport;
import com.hh.common.utils.ExceptionUtil;
import com.hh.common.utils.MessageUtils;
import com.hh.flow.service.HhDefService;
import com.hh.log.annotaion.Log;
import com.hh.log.enums.BusinessType;
import com.hh.mybatisflex.controller.BaseController;
import com.warm.flow.core.domain.entity.FlowDefinition;
import com.warm.flow.core.domain.entity.FlowNode;
import com.warm.flow.core.domain.entity.FlowSkip;
import com.warm.flow.core.service.DefService;
import com.warm.flow.core.service.SkipService;
import com.warm.mybatis.core.page.Page;
import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Random;

/**
 * 流程定义Controller
 *
 * @author hh
 * @date 2023-04-11
 */
@Validated
@RestController
@RequestMapping("/flow/definition")
public class DefController extends BaseController {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private HhDefService hhDefService;

    @Resource
    private DefService defService;

    @Resource
    private SkipService skipService;

    /**
     * 分页查询流程定义列表
     */
    @GetMapping("/list")
    public TableDataInfo<FlowDefinition> list(FlowDefinition flowDefinition) {
        try {
            // flow组件自带分页功能
            PageDomain pageDomain = TableSupport.buildPageRequest();
            Page<FlowDefinition> page = Page.pageOf(pageDomain.getPageNum(), pageDomain.getPageSize());
            page = defService.orderByCreateTime().desc().page(flowDefinition, page);
            TableDataInfo rspData = new TableDataInfo();
            rspData.setCode(HttpStatus.SUCCESS);
            rspData.setMsg("查询成功");
            rspData.setRows(page.getList());
            rspData.setTotal(page.getTotal());
            return rspData;
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.page");
            logger.error(msg, e);
            return TableDataInfo.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }


    /**
     * 获取流程定义详细信息
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:query')")
    @GetMapping(value = "/{id}")
    public R<FlowDefinition> getInfo(@PathVariable("id") Long id) {
        try {
            return R.ok(defService.getById(id));
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.detail");
            logger.error(msg, e);
            return R.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }

    /**
     * 获取流程定义详细信息
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:query')")
    @GetMapping(value = "/getNodeList/{definitionId}")
    public R<List<FlowNode>> getNodeList(@PathVariable("definitionId") Long definitionId) {
        return R.ok(hhDefService.getNodeList(definitionId));
    }

    /**
     * 获取流程定义详细信息
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:query')")
    @GetMapping(value = "/getSkipList/{nodeId}")
    public R<List<FlowSkip>> getSkipList(@PathVariable("nodeId") Long nodeId) {
        FlowSkip skip = new FlowSkip();
        skip.setNodeId(nodeId);
        return R.ok(skipService.list(skip));
    }

    /**
     * 新增流程定义
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:add')")
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @PostMapping
    @Transactional(rollbackFor = Exception.class)
    public R add(@RequestBody FlowDefinition flowDefinition) {
        try {
            return R.ok(defService.checkAndSave(flowDefinition));
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.add");
            logger.error(msg, e);
            return R.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }

    /**
     * 发布流程定义
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:publish')")
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @GetMapping("/publish/{id}")
    @Transactional(rollbackFor = Exception.class)
    public R publish(@PathVariable("id") Long id) {
        return R.ok(defService.publish(id));
    }

    /**
     * 取消发布流程定义
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:publish')")
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @GetMapping("/unPublish/{id}")
    @Transactional(rollbackFor = Exception.class)
    public R<Void> unPublish(@PathVariable("id") Long id) {
        defService.unPublish(id);
        return R.ok();
    }

    /**
     * 保存流程结点
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:saveNode')")
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @PostMapping("/saveNode")
    @Transactional(rollbackFor = Exception.class)
    public R<Void> saveNode(@RequestBody List<FlowNode> nodeList, Long definitionId) {
        try {
            hhDefService.saveNode(nodeList, definitionId);
            return R.ok();
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.save");
            logger.error(msg, e);
            return R.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }

    /**
     * 保存流程跳转
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:saveNode')")
    @Log(title = "流程定义", businessType = BusinessType.INSERT)
    @PostMapping("/saveSkip")
    @Transactional(rollbackFor = Exception.class)
    public R<Void> saveSkip(@RequestBody List<FlowSkip> skipList, Long nodeId) {
        try {
            hhDefService.saveSkip(skipList, nodeId);
            return R.ok();
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.save");
            logger.error(msg, e);
            return R.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }

    /**
     * 修改流程定义
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:edit')")
    @Log(title = "流程定义", businessType = BusinessType.UPDATE)
    @PutMapping
    @Transactional(rollbackFor = Exception.class)
    public R edit(@RequestBody FlowDefinition flowDefinition) {
        try {
            return R.ok(defService.updateById(flowDefinition));
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.update");
            logger.error(msg, e);
            return R.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }

    /**
     * 删除流程定义
     */
    @PreAuthorize("@ss.hasPermi('flow:definition:remove')")
    @Log(title = "流程定义", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    @Transactional(rollbackFor = Exception.class)
    public R remove(@PathVariable List<Long> ids) {
        try {
            return R.ok(defService.removeDef(ids));
        } catch (Exception e) {
            String msg = MessageUtils.message("controller.delete");
            logger.error(msg, e);
            return R.fail(ExceptionUtil.handleMsg(msg, e));
        }
    }

    @Log(title = "流程定义", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('flow:definition:importDefinition')")
    @PostMapping("/importDefinition")
    @Transactional(rollbackFor = Exception.class)
    public R<Void> importDefinition(MultipartFile file) throws Exception {
        defService.importXml(file.getInputStream());
        return R.ok();
    }

    @Log(title = "流程定义", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('flow:definition:exportDefinition')")
    @PostMapping("/exportDefinition/{id}")
    public void exportDefinition(@PathVariable("id") Long id, HttpServletResponse response) throws Exception {
        Document document = defService.exportXml(id);
        // 设置生成xml的格式
        OutputFormat of = OutputFormat.createPrettyPrint();
        // 设置编码格式
        of.setEncoding("UTF-8");
        of.setIndent(true);
        of.setIndent("    ");
        of.setNewlines(true);

        // 创建一个xml文档编辑器
        XMLWriter writer = new XMLWriter(response.getOutputStream(), of);
        writer.setEscapeText(false);
        response.reset();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/x-msdownload");
        response.setHeader("Content-Disposition", "attachment;");
        writer.write(document);
        writer.close();
    }

    @GetMapping("/graphics")
    public void graphics(HttpServletResponse response) throws IOException {
        response.setContentType("image/jpeg");// 声明文件格式
        // 绘制宽=480，长=640的图板
        int width = 720, hight = 720;
        BufferedImage image = new BufferedImage(width, hight, BufferedImage.TYPE_INT_RGB);
        // 获取图形上下文,graphics想象成一个画笔
        Graphics2D graphics = (Graphics2D) image.getGraphics();

        // 消除线条锯齿
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // 对指定的矩形区域填充颜色
        graphics.setColor(Color.WHITE);    // GREEN:绿色；  红色：RED;   灰色：GRAY
        graphics.fillRect(0, 0, 720, 720);

        /*
         *绘制一个开始圆形
         */
        graphics.setColor(Color.GREEN);
        int xStartOval = 100, yStartOval = 560;
        graphics.drawOval(xStartOval, yStartOval, 25, 25);

        /*
         * 画线 x,y是坐标，定义线段的两个坐标点
         */
        graphics.setColor(Color.BLACK);
        int x = 125, y = 572;
        graphics.drawLine(x, y, 200, y);

        /*
         * 画出一个闭合多边形(三角形)
         */
        int[] xPoints1 = {200, 200, 210};
        int[] yPoints1 = {577, 567, 572};
        graphics.drawPolygon(xPoints1, yPoints1, 3);

        /*
         *绘制一个矩形
         */
        // graphics.setColor(Color.GRAY);//--设置矩形边框颜色 。GREEN:绿色；  红色：RED;   灰色：GRAY
        int xRect = 210, yRect = 542;
        graphics.drawRoundRect(xRect, yRect, 80, 60, 20, 20);

        /*
         * 画线 x,y是坐标，定义线段的两个坐标点
         */
        graphics.setColor(Color.BLACK);
        int x1 = 290, y1 = 572;
        graphics.drawLine(x1, y1, 365, y);

        /*
         * 画出一个闭合多边形(三角形)
         */
        int[] xPoints2 = {365, 365, 375};
        int[] yPoints2 = {577, 567, 572};
        graphics.drawPolygon(xPoints2, yPoints2, 3);

        /*
         *画出一个折线
         */
        int[] xPoints = {250, 250, 415, 415};
        int[] yPoints = {532, 512, 512, 532};
        graphics.drawPolyline(xPoints, yPoints, 4);

        /*
         * 画出一个闭合多边形(三角形)
         */
        int[] xPoints3 = {245, 250, 255};
        int[] yPoints3 = {532, 542, 532};
        graphics.drawPolygon(xPoints3, yPoints3, 3);

        /*
         * 画出一个闭合多边形(三角形)
         */
        int[] xPoints4 = {410, 415, 420};
        int[] yPoints4 = {532, 542, 532};
        graphics.drawPolygon(xPoints4, yPoints4, 3);

        /*
         *绘制一个矩形
         */
        // graphics.setColor(Color.GRAY);//--设置矩形边框颜色 。GREEN:绿色；  红色：RED;   灰色：GRAY
        int xRect1 = 375, yRect1 = 542;
        graphics.drawRoundRect(xRect1, yRect1, 80, 60, 20, 20);

        /*
         * 画线 x,y是坐标，定义线段的两个坐标点
         */
        graphics.setColor(Color.BLACK);
        int x2 = 455, y2 = 572;
        graphics.drawLine(x2, y2, 550, y);

        /*
         * 画出一个闭合多边形(三角形)
         */
        int[] xPoints5 = {550, 550, 560};
        int[] yPoints5 = {577, 567, 572};
        graphics.drawPolygon(xPoints5, yPoints5, 3);

        /*
         *绘制一个结束圆形
         */
        graphics.setColor(Color.RED);
        int xEndOval1 = 560, yEndOval1 = 560;
        graphics.fillOval(xEndOval1, yEndOval1, 25, 25);


        // 生成随机数
        Random random = new Random();

        // 设置文字颜色
        graphics.setColor(new Color(20 + random.nextInt(100), 20 + random.nextInt(100), 20 + random.nextInt(100)));
        // 设置文字内容、位置
        graphics.drawString("直线", 100 + 50, 100 - 5);
        graphics.drawString("折线", 200, 150 - 5);
        graphics.drawString("空心三角形", 110, 280);
        graphics.drawString("实心菱形", 500 - 20, 280);
        graphics.drawString("椭圆形", 100 + 50, 360 + 50);
        graphics.drawString("矩形", 440 + 50, 360 + 50);
        // graphics.drawString("错误的背景颜色", 100, 540);

        // graphics.setPaintMode();
        // graphics.translate(400, 600);

        graphics.dispose();// 释放此图形的上下文并释放它所使用的所有系统资源

        ImageIO.write(image, "JPEG", response.getOutputStream());
        PrintWriter out = response.getWriter();
        out.flush();
        out.close();
    }

    // @GetMapping("/graphics")
    // public void graphics(HttpServletResponse response) throws IOException {
    //     response.setContentType("image/jpeg");//声明文件格式
    //     //绘制宽=480，长=640的图板
    //     int width=720,hight=480;
    //     BufferedImage image = new BufferedImage(width,hight,BufferedImage.TYPE_INT_RGB);
    //     //获取图形上下文,graphics想象成一个画笔
    //     Graphics2D graphics = (Graphics2D)image.getGraphics();
    //
    //     //消除线条锯齿
    //     graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    //
    //     //对指定的矩形区域填充颜色
    //     graphics.setColor(Color.WHITE);	//GREEN:绿色；  红色：RED;   灰色：GRAY
    //     graphics.fillRect(0, 0, 720, 480);
    //
    //     //生成随机数
    //     Random random = new Random();
    //     /*
    //      * 画线 x,y是坐标，定义线段的两个坐标点
    //      */
    //     graphics.setColor(Color.BLACK);
    //     int x=100,y=100,x1=100,y1=y;
    //     graphics.drawLine(x,y,x+x1,y1);
    //     /*
    //      *画出一个折线
    //      */
    //     int[] xPoints = {100,100,250,250};
    //     int[] yPoints = {180,150,150,180};
    //     graphics.drawPolyline(xPoints, yPoints, 4);
    //     /*
    //      * 画出一个闭合多边形(三角形)
    //      */
    //     int[] xPoints1 = {100,100,200};
    //     int[] yPoints1 = {240,320,280};
    //     graphics.drawPolygon(xPoints1, yPoints1, 3);
    //     /*
    //      * 画出一个闭合多边形(菱形)
    //      */
    //     int[] xPoints2 = {440,500,560,500};
    //     int[] yPoints2 = {280,240,280,320};
    //     graphics.drawPolygon(xPoints2, yPoints2, 4);
    //     graphics.setColor(Color.ORANGE);
    //     graphics.fillPolygon(xPoints2, yPoints2, 4);
    //     /*
    //      *绘制一个椭圆形
    //      */
    //     graphics.setColor(Color.GREEN);
    //     int xOval=100,yOval=360;
    //     graphics.drawOval(xOval, yOval, 100, 100);
    //
    //     /*
    //      *绘制一个矩形
    //      */
    //     //graphics.setColor(Color.GRAY);//--设置矩形边框颜色 。GREEN:绿色；  红色：RED;   灰色：GRAY
    //     int xRect=440,yRect=360;
    //     graphics.drawRoundRect(xRect, yRect, 200, 100, 40, 40);
    //
    //     //设置文字颜色
    //     graphics.setColor(new Color( 20+random.nextInt(100),  20+random.nextInt(100),  20+random.nextInt(100) ));
    //     //设置文字内容、位置
    //     graphics.drawString("直线",100+50,100-5);
    //     graphics.drawString("折线", 200, 150-5);
    //     graphics.drawString("空心三角形", 110, 280);
    //     graphics.drawString("实心菱形", 500-20, 280);
    //     graphics.drawString("椭圆形", 100+50, 360+50);
    //     graphics.drawString("矩形", 440+50, 360+50);
    //     //graphics.drawString("错误的背景颜色", 100, 540);
    //
    //     //graphics.setPaintMode();
    //     //graphics.translate(400, 600);
    //
    //     graphics.dispose();//释放此图形的上下文并释放它所使用的所有系统资源
    //
    //     ImageIO.write(image,"JPEG",response.getOutputStream());
    //     PrintWriter out = response.getWriter();
    //     out.flush();
    //     out.close();
    // }
}
